#ifndef GAMEMANAGER_H
#define GAMEMANAGER_H

#include "Game.h"
#include "UserInfo.h"

#include "Game/SocketDefine.h"
#include "_Global/GlobalClass.h"
#include "_Global/VersionCheck/VersionCheck.h"

#include <QObject>
#include <QApplication>


class QQmlApplicationEngine;
class QQuickWindow;
class WordLib;
class TcpSocket;
//class Game;
//class UserInfo;

//管理登录窗口和游戏窗口
//负责传递Socket消息
class GameManager : public QObject
{
    Q_OBJECT
    //Q_ENUMS(_ClientGameStatus)
    Q_PROPERTY(QObject* userInfo READ userInfo)
    Q_PROPERTY(QObject* gameCore READ gameCore)
    Q_PROPERTY(QObject* wordLib READ wordLib)
    Q_PROPERTY(QString platform READ platform)
    Q_PROPERTY(QVariantMap gameConfig READ gameConfig)  //QVariantMap不用qml注册,因为它就是js中的 对象

public:
    //创建登录窗口,注册窗口,大厅窗口,游戏窗口,链接信号槽
    explicit GameManager(QObject *parent = nullptr);
    virtual ~GameManager();

    bool InitOnce();

signals:
    //void s_ConnectServerErr(int errType,int errValue);

    //To QML:
    void s_StartGame();         //游戏开始
    void s_OverGame(GameCore::_GameStatus nRet);    //游戏结束

    void s_qml_Message(QString msg, int level);     //游戏信息,level:0信息;1警告;2退出
    void s_qml_UpdateInfo(QString url, int type);   //升级信息,type:-1(版本检测出错),0(不升级),1(建议),2(强制升级)

    //通知qml本人加入房间
    void s_qml_JoinGroup(int gID);
    //通知qml其他人加入房间
    void s_qml_OthersJoinGroup(QString nickName, bool bIn);
    //准备信号
    void s_qml_OthersReadyInGroup(QString nickName, qint16 status, qint16 duiWu);
    //聊天信息
    void s_qml_OthersMessage(qint16 type, qint16 seatID, QString msg);

    //改变所有窗口visible
    //type:1(退出到登录界面);2(退出到服务器选择界面)
    void s_qml_ChangeAllWindowVisible(int type);


    void s_qml_DebugMsg(QString msg);               //调试信息(出现在调试框)



//网络处理
public:
    //客户端socket数据处理
    //From GameCore
    void OnInfoReadyRead(TcpSocket* sock);
    void OnGameReadyRead(TcpSocket* sock);

    //使用sock的加密ba后发送,密码在listTransfersCodeData中
    //返回true表示发送成功,false为加入队列或其他
    bool SendWithCode(TcpSocket* sock, QByteArray ba = QByteArray())
    {
        //QByteArray baCode;
        if(sock->m_listOutTransfersCode.count() > 0)
        {
            /*
            int n = sock->outTransfersCode % (qint16(sizeof(transfersCodeString) / sizeof(const char*)));
            baCode.append(transfersCodeString[n],sizeof(transfersCodeString[n]));
            */
            qint16 outTransfersCode = sock->m_listOutTransfersCode.takeFirst();
            qDebug() << "[GameManager]读取密码:" << listTransfersCodeData.at(outTransfersCode % listTransfersCodeData.length());
            return sock->sendUseTransfersCode(ba, listTransfersCodeData.at(outTransfersCode % listTransfersCodeData.length()));
        }
        else
        {
            qDebug() << "[GameManager]Code空";
            sock->sendUseTransfersCode(ba);
            return false;
        }
    }


//数据库处理
    int SaveConfigToDb(QString key, QString value); //存储数据key和value
    int DeleteConfigToDb(QString key);
    int LoadConfigFromDb();    //读取Config到Map

    //链接并读取本地数据库
    bool LoadDatabase();
    int CheckConfig();  //暂时无用!!!检查Config字段(主要是升级信息),<0出错;=0正常;>0重新连接数据库


//槽
public slots:

    //游戏开始，进行简单初始化
    //netPlay为true表示联网,否则为单机;玩家个数，单词的两个ID,
    //restart:0:继续下一关;1:清空记录重新开始;2:重新开始本关单词(!!!没完成!!!)
    //From QML
    void sl_StartGame(int playerCount, int cID, int lID, int restart, bool netPlay = false);

    //游戏结束(0表示正常结束,不需要释放Game;其他值表示需要释放)
    //From GameCore
    void sl_OverGame(GameCore::_GameStatus nRet);


    void sl_qml_SinglePlay(int playerCount, int cID, int lID, int restart)
    {
        sl_StartGame(playerCount,cID,lID,restart,false);
    }

    //qml切换学习方式
    void sl_qml_ChangeStudyType(int type)
    {
        m_pWordLib->m_nType = type;
        //qDebug() << "!!!type:" << type;
    }


//其他功能请求
public slots:
    //增加设置项
    void sl_qml_SetGameConfig(QString k, QVariant v)
    {
        m_mapGameConfig.insert(k, v);
    }
    //存储设置项
    int sl_SaveConfigToDb(QString key, QString value) //存储数据key和value
    {
        return SaveConfigToDb(key, value);
    }
    void sl_SetSound(bool music, bool effect)
    {
        if(music)
            SaveConfigToDb("MusicOn", "1");
        else
            SaveConfigToDb("MusicOn", "0");

        if(effect)
            SaveConfigToDb("EffectOn", "1");
        else
            SaveConfigToDb("EffectOn", "0");
    }
    //设置游戏速度
    void sl_SetSpeed(int value)
    {
        switch (value)
        {
        case 1:     //快速
            m_pGameCore->m_nGameMessageDelay = 1000;
            SaveConfigToDb("GameMessageDelay", "1000");
            SaveConfigToDb("QuestionShowDelay", "1500");
            SaveConfigToDb("ComQuestionChoiceDelay", "3000");
            break;
        case 2:     //慢速
            m_pGameCore->m_nGameMessageDelay = 2000;
            SaveConfigToDb("GameMessageDelay", "2000");
            SaveConfigToDb("QuestionShowDelay", "3500");
            SaveConfigToDb("ComQuestionChoiceDelay", "5000");
            break;
        default:    //默认
            m_pGameCore->m_nGameMessageDelay = 1500;
            SaveConfigToDb("GameMessageDelay", "1500");
            SaveConfigToDb("QuestionShowDelay", "2500");
            SaveConfigToDb("ComQuestionChoiceDelay", "4000");
            break;
        }
    }
    //显示动态属性
    QVariant sl_ShowProperty(const char *name)
    {
        //return this->property(prop.toLocal8Bit().constData());
        return property(name);
    }

    QString sl_ApplicationPath()
    {
        return qApp->applicationDirPath();
    }


//qml 房间处理 发送信息
public slots:

    //创建一个房间
    void sl_qml_CreateGroup(int maxPlayerCount = 2,const QString& password = "", quint32 classID = 0);

    //退出房间
    void sl_qml_ExitGroup();

    //加入房间
    void sl_qml_JoinGroup(qint32 gid, QString password = "");

    //qml游戏准备
    void sl_qml_GetReady(qint16 duiWu);

    //qml游戏开始
    void sl_qml_StartGame();

    //发送信息,type为1表示游戏中信息,为2表示房间内信息
    void sl_qml_SendMessage(QString msg, qint16 type);


    //用户强制退出,则扣分
    void sl_qml_TerminateGame(int code)
    {
        //pGameCore->m_bTerminateGame = true;
        m_pGameCore->TerminateGame(code, GameCore::Game_Status_Terminated);
    }

    //From QML
    void sl_qml_DebugButton(int button, QVariant v);


public:
    void NetLog(QByteArray &ba, bool s)
    {
        /*
        QFile netLog("netLogs.log");
        if(s)
            netLog.setFileName("netsLog.log");
        netLog.open(QIODevice::Append);
        netLog.write(ba.toHex());
        netLog.write("\r\n--------------------------\r\n");
        netLog.close();
        */
    }


//属性
public:
    QObject* userInfo() const
    {
        return m_pUserInfo;
    }
    QObject* gameCore() const
    {
        return m_pGameCore;
    }
    QString platform() const
    {
#ifdef QT_NO_DEBUG
        return "release";
#else
        return "debug";
#endif
    }
    QVariantMap gameConfig()
    {
        return m_mapGameConfig;
    }

    QObject* wordLib() const;


//数据
public:
    //游戏设置（本地）
    QVariantMap m_mapGameConfig;   //数据库读取的配置
    Config m_ConfigFile;          //文件中读取的配置

protected:
    //QQuickWindow *pLoginWindow;
    //QQuickWindow *pRegisterWindow;
    //QQuickWindow *pGameCenterWindow;
    QQuickWindow *m_pGameWindow;
    //QQuickWindow *pDebugWindow;

    //QThread     *pGameThread;

    Game        *m_pGameCore;
    UserInfo    *m_pUserInfo;
    WordLib     *m_pWordLib;

    TcpSocket   *m_pInfoSocket;
    TcpSocket   *m_pGameSocket;

    QQmlApplicationEngine *m_pAppQmlEngine;

    VersionCheck m_VersionCheck;

};

#endif // GAMEMANAGER_H
